package impl

import (
	"errors"
	"fsd/fight"
	"github.com/golang/protobuf/proto"
)

type Cmd2Pb struct {
}

func (*Cmd2Pb) C2SMsgerType(cmd uint16) (fight.Msger, error) {
	switch cmd {
	case fight.PT_CMD_LOGIN:
		return &PbLoginReqMsg{}, nil
	case fight.PT_CMD_LOADING:
		return &PbNullMsg{}, nil
	case fight.PT_CMD_TIMELINE:
		return &PbNullMsg{}, nil
	case fight.PT_CMD_HEART_BEAT:
		return &PbNullMsg{}, nil
	case fight.PT_CMD_UPLOAD:
		return &PbUploadFrameMsg{}, nil
	case fight.PT_CMD_SETTLE:
		return &PbSettleReqMsg{}, nil
	default:
		return nil, errors.New("Invalid C2S Cmd")
	}
}

func (*Cmd2Pb) S2CMsgerType(cmd uint16) (fight.Msger, error) {
	switch cmd {
	case fight.PT_CMD_LOGIN:
		return &PbLoginAckMsg{}, nil
	case fight.PT_CMD_ALL_LOGINED:
		return &PbNullMsg{}, nil
	case fight.PT_CMD_ALL_LOADED:
		return &PbNullMsg{}, nil
	case fight.PT_CMD_LOADING:
		return &PbLoadAckMsg{}, nil
	case fight.PT_CMD_TIMELINE:
		return &PbTimelineAckMsg{}, nil
	case fight.PT_CMD_HEART_BEAT:
		return &PbNullMsg{}, nil
	case fight.PT_CMD_BROADCAST:
		return &PbBroadcastFrameMsg{}, nil
	case fight.PT_CMD_SETTLE:
		return &PbSettleAckMsg{}, nil
	default:
		return nil, errors.New("Invalid S2C Cmd")
	}
}

// IMPLEMENT INTERFACE: fight.LoginReqMsger
type PbLoginReqMsg struct {
	*fight.FsdBaseMsg
	PbFightLoginReq
}

func (m *PbLoginReqMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightLoginReq)
}

func (m *PbLoginReqMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightLoginReq)
}

func (m *PbLoginReqMsg) GetLoginReqUserId() int32 {
	return m.PbFightLoginReq.GetUserId()
}

func (m *PbLoginReqMsg) SetLoginReqUserId(userId int32) {
	m.UserId = proto.Int32(userId)
}

func (m *PbLoginReqMsg) GetLoginReqFightId() uint64 {
	return m.PbFightLoginReq.GetFightId()
}

func (m *PbLoginReqMsg) SetLoginReqFightId(fightId uint64) {
	m.FightId = proto.Uint64(fightId)
}

// IMPLEMENT INTERFACE: fight.LoginAckMsger
type PbLoginAckMsg struct {
	*fight.FsdBaseMsg
	PbFightLoginAck
}

func (m *PbLoginAckMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightLoginAck)
}

func (m *PbLoginAckMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightLoginAck)
}

func (m *PbLoginAckMsg) GetLoginAckRet() int32 {
	return m.PbFightLoginAck.GetRet()
}

func (m *PbLoginAckMsg) SetLoginAckRet(ret int32) {
	m.Ret = proto.Int32(ret)
}

func (m *PbLoginAckMsg) GetLoginAckGameState() int32 {
	return m.PbFightLoginAck.GetGameState()
}

func (m *PbLoginAckMsg) SetLoginAckGameState(gamState int32) {
	m.GameState = proto.Int32(gamState)
}

// IMPLEMENT INTERFACE: fight.LoadAckMsger
type PbLoadAckMsg struct {
	*fight.FsdBaseMsg
	PbFightLoadAck
}

func (m *PbLoadAckMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightLoadAck)
}

func (m *PbLoadAckMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightLoadAck)
}

func (m *PbLoadAckMsg) GetLoadAckRet() int32 {
	return m.PbFightLoadAck.GetRet()
}

func (m *PbLoadAckMsg) SetLoadAckRet(ret int32) {
	m.Ret = proto.Int32(ret)
}

// IMPLEMENT INTERFACE: fight.TimelineAckMsger
type PbTimelineAckMsg struct {
	*fight.FsdBaseMsg
	PbFightTimelineAck
}

func (m *PbTimelineAckMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightTimelineAck)
}

func (m *PbTimelineAckMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightTimelineAck)
}

func (m *PbTimelineAckMsg) GetTimelineAckRet() int32 {
	return m.PbFightTimelineAck.GetRet()
}

func (m *PbTimelineAckMsg) SetTimelineAckRet(ret int32) {
	m.Ret = proto.Int32(ret)
}

// IMPLEMENT INTERFACE: fight.UploadFrameMsger
type PbUploadFrameMsg struct {
	*fight.FsdBaseMsg
	PbFightUploadFrame
}

func (m *PbUploadFrameMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightUploadFrame)
}

func (m *PbUploadFrameMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightUploadFrame)
}

func (m *PbUploadFrameMsg) GetUploadFrameCmdId() int32 {
	return m.PbFightUploadFrame.GetCmdId()
}

func (m *PbUploadFrameMsg) SetUploadFrameCmdId(cmdId int32) {
	m.CmdId = proto.Int32(cmdId)
}

func (m *PbUploadFrameMsg) GetUploadFrameId() int32 {
	return m.PbFightUploadFrame.GetFrame()
}

func (m *PbUploadFrameMsg) SetUploadFrameId(frame int32) {
	m.Frame = proto.Int32(frame)
}

func (m *PbUploadFrameMsg) SetUploadFrameData(i interface{}) {
	if data, ok := i.([]byte); ok {
		m.Data = data
	}
}

// IMPLEMENT INTERFACE: fight.BroadcastFrameMsger
type PbBroadcastFrameMsg struct {
	*fight.FsdBaseMsg
	PbFightBroadcastFrame
}

func (m *PbBroadcastFrameMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightBroadcastFrame)
}

func (m *PbBroadcastFrameMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightBroadcastFrame)
}

func (m *PbBroadcastFrameMsg) GetBroadcastFrameId() int32 {
	return m.PbFightBroadcastFrame.GetFrame()
}

func (m *PbBroadcastFrameMsg) SetBroadcastFrameId(frame int32) {
	m.Frame = proto.Int32(frame)
}

func (m *PbBroadcastFrameMsg) GetBroadcastFrameTimeline() int32 {
	return m.PbFightBroadcastFrame.GetTimeline()
}

func (m *PbBroadcastFrameMsg) SetBroadcastFrameTimeline(timeline int32) {
	m.Timeline = proto.Int32(timeline)
}

func (m *PbBroadcastFrameMsg) AppendBroadcastFrameDatas(userId int32, i fight.UploadFrameMsger) {
	frameDatas := m.GetFrameDatas()
	if pbUploadFrameMsg, ok := i.(*PbUploadFrameMsg); ok {
		pbUploadFrameMsg.UserId = proto.Int32(userId)
		frameDatas = append(frameDatas, &pbUploadFrameMsg.PbFightUploadFrame)
		m.FrameDatas = frameDatas
	}
}

// IMPLEMENT INTERFACE: fight.OverReqMsger
type PbSettleReqMsg struct {
	*fight.FsdBaseMsg
	PbFightSettleReq
}

func (m *PbSettleReqMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightSettleReq)
}

func (m *PbSettleReqMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightSettleReq)
}

func (m *PbSettleReqMsg) SetSettleReqResult(i interface{}) {
	if result, ok := i.(int32); ok {
		m.Result = proto.Int32(result)
	}
}

// IMPLEMENT INTERFACE: fight.OverAckMsger
type PbSettleAckMsg struct {
	*fight.FsdBaseMsg
	PbFightSettleAck
}

func (m *PbSettleAckMsg) Decode(payload []byte) error {
	return proto.Unmarshal(payload, &m.PbFightSettleAck)
}

func (m *PbSettleAckMsg) Encode() ([]byte, error) {
	return proto.Marshal(&m.PbFightSettleAck)
}

func (m *PbSettleAckMsg) AppendSettleAckResults(userId int32, i fight.SettleReqMsger) {
	results := m.GetResults()
	if pbSettleReqMsg, ok := i.(*PbSettleReqMsg); ok {
		result := &PbFightResult{
			UserId: proto.Int32(userId),
			Result: proto.Int32(pbSettleReqMsg.GetResult()),
		}
		results = append(results, result)
		m.Results = results
	}
}

// IMPLEMENT INTERFACE: fight.NullMsger
type PbNullMsg struct {
	*fight.FsdBaseMsg
}

func (*PbNullMsg) Decode(payload []byte) error {
	return nil
}

func (*PbNullMsg) Encode() ([]byte, error) {
	return []byte{}, nil
}
